package cn.lijiajia3515.cairo.auth.framework.security.user;

import cn.lijiajia3515.cairo.auth.domain.mongo.AccountMongo;
import cn.lijiajia3515.cairo.auth.domain.mongo.AuthMongoConstants;
import cn.lijiajia3515.cairo.auth.framework.AccountRepository;
import cn.lijiajia3515.cairo.auth.framework.security.CairoAuthAccount;
import cn.lijiajia3515.cairo.auth.modules.auth.AuthType;
import cn.lijiajia3515.cairo.domain.CairoAccount;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

import java.util.Optional;

public class CairoUserService implements UserDetailsService {
	private final MongoTemplate mongoTemplate;
	private final AccountRepository repository;
	private final String CLIENT = "cairo";

	public CairoUserService(MongoTemplate mongoTemplate, AccountRepository repository) {
		this.mongoTemplate = mongoTemplate;
		this.repository = repository;
	}

	@Override
	public CairoAuthAccount loadUserByUsername(String username) throws UsernameNotFoundException {
		Query query = Query.query(
			new Criteria()
				.orOperator(
					Criteria.where(AccountMongo.FIELD.ID).is(username),
					Criteria.where(AccountMongo.FIELD.USERNAME).is(username),
					Criteria.where(AccountMongo.FIELD.PHONE_NUMBER).is(username),
					Criteria.where(AccountMongo.FIELD.EMAIL).is(username)
				)
		).with(Sort.by(
			Sort.Order.asc(AccountMongo.FIELD.META.CREATED.AT),
			Sort.Order.asc(AccountMongo.FIELD.META.LAST_MODIFIED.AT),
			Sort.Order.asc(AccountMongo.FIELD._ID)
		));
		query.fields().include(AccountMongo.FIELD.ID, AccountMongo.FIELD.PASSWORD);
		return Optional.ofNullable(mongoTemplate.findOne(query, AccountMongo.class, AuthMongoConstants.Collection.ACCOUNT))
			.filter(x -> x.getId() != null && x.getPassword() != null)
			.map(um -> {
				CairoAccount account = repository.getAccount(CLIENT, um.getId());
				return CairoAuthAccount.builder()
					.authorities(repository.getAuthority(CLIENT, um.getId()))

					.id(account.getId())
					.login(account.getLogin())
					.phoneNumber(account.getPhoneNumber())
					.accountEnabled(um.getAccountEnabled())
					.accountLocked(um.getAccountLocked())

					.nickname(account.getNickname())
					.avatarUrl(account.getAvatarUrl())
					.roles(account.getRoles())
					.departments(account.getDepartments())

					.password(um.getPassword())
					.type(AuthType.Password)
					.build();
			})
			.orElseThrow(() -> new UsernameNotFoundException("用户名或密码错误"));
	}


}
